package com.igo.util;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.stream.CollectorUtil;
import cn.hutool.core.util.IdUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.igo.domain.datacollection.devicedata.DeviceDataCalcd;
import com.igo.domain.datacollection.devicedata.FlatCarData;
import com.igo.domain.datacollection.devicedata.GantryCraneCaData;
import com.igo.enums.devicedata.CalcdTypeEnum;
import com.igo.mapper.devicedata.*;
import com.igo.service.devicedata.FlatCarDataService;
import com.igo.service.devicedata.GantryCraneCaDataService;
import com.igo.service.devicedata.DeviceDataCalcdService;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;

@Component
public class DeviceDataCalculateUtill {

    private ExecutorService es = Executors.newFixedThreadPool(2000);

    @Resource
    private DeviceDataMapper deviceDataMapper;

    @Resource
    private DeviceInfoMapper deviceInfoMapper;

    @Resource
    private FlatCarDataService flatCarDataService;

    @Resource
    private FlatCarDataMapper flatCarDataMapper;

    @Resource
    private GantryCraneCaDataMapper gantryCraneCaDataMapper;

    @Resource
    private GantryCraneCaDataService gantryCraneCaDataService;

    @Resource
    private DeviceDataCalcdMapper deviceDataCalcdMapper;

    @Resource
    private DeviceDataCalcdService deviceDataCalcdService;

    private Date startTime;

    private Date endTime;


    public void crashData(Date strStartTime, Date strEndTime) {
        //查询所有任务载重数据
//        String strStartTime = "2024-10-01 00:00:00";
//        Date start = DateUtil.parse(strStartTime);
////        String strEndTime = "2025-01-12 23:59:59";
//        Date end = DateUtil.parse(strEndTime);
        //时间分布没有数据时,插入一条离线数据
        List<GantryCraneCaData> insertGantryCraneCaDataList = new ArrayList<>();
        List<FlatCarData> insertFlatCarDataList = new ArrayList<>();
        while(strStartTime.compareTo(strEndTime)<=0){
            endTime = DateUtil.offset(strStartTime, DateField.DAY_OF_MONTH, 1);
            endTime=DateUtil.offset(endTime, DateField.SECOND, -1);
            //获取设备的天的数据

            List<FlatCarData> flatCarDataDayList = flatCarDataService.list(new LambdaQueryWrapper<FlatCarData>()
                    .ge(FlatCarData::getCreateTime, strStartTime).le(FlatCarData::getCreateTime, strEndTime));
            List<GantryCraneCaData> gantryCraneCaDataDayList = gantryCraneCaDataService.list(new LambdaQueryWrapper<GantryCraneCaData>()
                    .ge(GantryCraneCaData::getCreateTime, strStartTime).le(GantryCraneCaData::getCreateTime, strEndTime));
            List<String> deviceNos = flatCarDataDayList.stream().map(FlatCarData::getDeviceNo).distinct().collect(Collectors.toList());
            if(CollectionUtil.isNotEmpty(flatCarDataDayList)){
                deviceNos.stream().forEach(deviceNo->{
                    List<FlatCarData> flatCarDataDays = flatCarDataDayList.stream().filter(flatCarData ->
                            deviceNo.equals(flatCarData.getDeviceNo())).sorted((Comparator.comparing(FlatCarData::getCreateTime))).collect(Collectors.toList());
                    if (CollectionUtil.isNotEmpty(flatCarDataDays)){
                        List<FlatCarData> flatCarData = fillOfflineFlatCarData(flatCarDataDays);
                        if (CollectionUtil.isNotEmpty(flatCarData)){
                            insertFlatCarDataList.addAll(flatCarData);
                        }
                    }
                });
            }
            if(CollectionUtil.isNotEmpty(gantryCraneCaDataDayList)){
                deviceNos.stream().forEach(deviceNo->{
                    List<GantryCraneCaData> gantryCraneCaDataDays = gantryCraneCaDataDayList.stream().filter(flatCarData ->
                            deviceNo.equals(flatCarData.getDeviceNo())).sorted((Comparator.comparing(GantryCraneCaData::getCreateTime))).collect(Collectors.toList());
                    if (CollectionUtil.isNotEmpty(gantryCraneCaDataDays)){
                        List<GantryCraneCaData> gantryCraneCaData = fillOfflineGantryCraneCaData(gantryCraneCaDataDays);
                        if (CollectionUtil.isNotEmpty(gantryCraneCaData)){
                            insertGantryCraneCaDataList.addAll(gantryCraneCaData);
                        }
                    }
                });
            }
            strStartTime=DateUtil.offset(endTime, DateField.SECOND, 1);
        }
        if (CollectionUtil.isNotEmpty(insertGantryCraneCaDataList)){
            gantryCraneCaDataService.saveBatch(insertGantryCraneCaDataList);
        }
        if (CollectionUtil.isNotEmpty(insertFlatCarDataList)){
            flatCarDataService.saveBatch(insertFlatCarDataList);
        }
    }

    /***
     *
     * @param flatCarDataList
     * @return
     */
    public List<FlatCarData> fillOfflineFlatCarData(List<FlatCarData> flatCarDataList){
        List<FlatCarData> insertFlatCarDataList = new ArrayList<>();
        //当天开始时间
        DateTime beginOfDay = DateUtil.beginOfDay(flatCarDataList.get(0).getDataTime());
        long betweenMin = DateUtil.between(beginOfDay,flatCarDataList.get(0).getDataTime(),DateUnit.MINUTE);
        if (betweenMin>=3){
            List<FlatCarData> flatCarData = fillOfflineFlatCarData(beginOfDay, flatCarDataList.get(0).getDataTime(), "3",flatCarDataList.get(0).getDeviceNo());
            insertFlatCarDataList.addAll(flatCarData);
        }
        for (int i = 0,j=i+1; i <flatCarDataList.size()-1 && j<flatCarDataList.size()-1; i++,j++) {
            FlatCarData preFlatCarData = flatCarDataList.get(i);
            FlatCarData seqFlatCarData = flatCarDataList.get(j);
            long betweenTime = DateUtil.between(preFlatCarData.getDataTime(), seqFlatCarData.getDataTime(), DateUnit.MINUTE);
            if (betweenTime>=3){
                List<FlatCarData> flatCarData = fillOfflineFlatCarData(preFlatCarData.getDataTime(),seqFlatCarData.getDataTime(), "2",flatCarDataList.get(0).getDeviceNo());
                insertFlatCarDataList.addAll(flatCarData);
            }
        }
        //非当天数据做尾部填充
        if (!(DateUtil.parse(DateUtil.today(), "yyyy-MM-dd").compareTo(
                DateUtil.parse(DateUtil.format(flatCarDataList.get(0).getDataTime(), "yyyy-MM-dd HH:mm:ss"), "yyyy-MM-dd"))==0)){
            DateTime endOfDay = DateUtil.endOfDay(flatCarDataList.get(flatCarDataList.size()-1).getDataTime());
            long betweenTime = DateUtil.between(flatCarDataList.get(flatCarDataList.size()-1).getDataTime(),endOfDay,DateUnit.MINUTE);
            if (betweenTime>=3){
                List<FlatCarData> flatCarData = fillOfflineFlatCarData(flatCarDataList.get(flatCarDataList.size()-1).getDataTime(),endOfDay, "1",flatCarDataList.get(0).getDeviceNo());
                insertFlatCarDataList.addAll(flatCarData);
            }
        }
        return insertFlatCarDataList;
    }

    public List<GantryCraneCaData> fillOfflineGantryCraneCaData(List<GantryCraneCaData> gantryCraneCaDataList){
        List<GantryCraneCaData> insertGantryCraneCaDataList = new ArrayList<>();
        //当天开始时间
        DateTime beginOfDay = DateUtil.beginOfDay(gantryCraneCaDataList.get(0).getDataTime());
        long betweenMin = DateUtil.between(beginOfDay,gantryCraneCaDataList.get(0).getDataTime(),DateUnit.MINUTE);
        if (betweenMin>=3){
            List<GantryCraneCaData> GantryCraneCaData = fillOfflineGantryCraneCaData(beginOfDay, gantryCraneCaDataList.get(0).getDataTime(), "3",gantryCraneCaDataList.get(0).getDeviceNo());
            insertGantryCraneCaDataList.addAll(GantryCraneCaData);
        }
        for (int i = 0,j=i+1; i <gantryCraneCaDataList.size()-1 && j<gantryCraneCaDataList.size()-1; i++,j++) {
            GantryCraneCaData preGantryCraneCaData = gantryCraneCaDataList.get(i);
            GantryCraneCaData seqFGantryCraneCaData = gantryCraneCaDataList.get(j);
            long betweenTime = DateUtil.between(preGantryCraneCaData.getDataTime(), seqFGantryCraneCaData.getDataTime(), DateUnit.MINUTE);
            if (betweenTime>=3){
                List<GantryCraneCaData> gantryCraneCaData = fillOfflineGantryCraneCaData(preGantryCraneCaData.getDataTime(),seqFGantryCraneCaData.getDataTime(), "2",gantryCraneCaDataList.get(0).getDeviceNo());
                insertGantryCraneCaDataList.addAll(gantryCraneCaData);
            }
        }
        //非当天数据做尾部填充
        if (!(DateUtil.parse(DateUtil.today(), "yyyy-MM-dd").compareTo(
                DateUtil.parse(DateUtil.format(gantryCraneCaDataList.get(0).getDataTime(), "yyyy-MM-dd HH:mm:ss"), "yyyy-MM-dd"))==0)){
            DateTime endOfDay = DateUtil.endOfDay(gantryCraneCaDataList.get(gantryCraneCaDataList.size()-1).getDataTime());
            long betweenTime = DateUtil.between(gantryCraneCaDataList.get(gantryCraneCaDataList.size()-1).getDataTime(),endOfDay,DateUnit.MINUTE);
            if (betweenTime>=3){
                List<GantryCraneCaData> gantryCraneCaData = fillOfflineGantryCraneCaData(gantryCraneCaDataList.get(gantryCraneCaDataList.size()-1).getDataTime(),endOfDay, "1",gantryCraneCaDataList.get(0).getDeviceNo());
                insertGantryCraneCaDataList.addAll(gantryCraneCaData);
            }
        }
        return insertGantryCraneCaDataList;
    }

    /**
     *
     * @param startTime
     * @param endTime
     * @param type 1为头部不生成 2为头部尾部都不生成 3尾部不生成
     * @return
     */
    public List<FlatCarData> fillOfflineFlatCarData(Date startTime, Date endTime,String type,String deviceNo){
        List<FlatCarData> offlineFlatCarData = new ArrayList<>();
        Date start = DateUtil.parse(DateUtil.format(startTime, "yyyy-MM-dd HH:mm:ss"), "yyyy-MM-dd HH:mm");
        Date end = DateUtil.parse(DateUtil.format(endTime, "yyyy-MM-dd HH:mm:ss"), "yyyy-MM-dd HH:mm");
        if (type.equals("1")){
            start = DateUtil.offset(start, DateField.MINUTE, 1);
        }else if (type.equals("2")){
            start = DateUtil.offset(start, DateField.MINUTE, 1);
            end = DateUtil.offset(end, DateField.MINUTE, -1);
        }else if (type.equals("3")){
            end = DateUtil.offset(end, DateField.MINUTE, -1);
        }
        while(start.compareTo(end)<=0) {
            //新增离线数据
            FlatCarData flatCarData = new FlatCarData();
            flatCarData.setRunningState("0");
            flatCarData.setDeviceNo(deviceNo);
            flatCarData.setDataTime(start);
            flatCarData.setCreateTime(start);
            flatCarData.setLoadCapacity("0");
            offlineFlatCarData.add(flatCarData);
            start=DateUtil.offset(start, DateField.MINUTE, 1);
        }
        return offlineFlatCarData;
    }

    public List<GantryCraneCaData> fillOfflineGantryCraneCaData(Date startTime, Date endTime,String type,String deviceNo){
        List<GantryCraneCaData> offlineGantryCraneCaData = new ArrayList<>();
        Date start = DateUtil.parse(DateUtil.format(startTime, "yyyy-MM-dd HH:mm:ss"), "yyyy-MM-dd HH:mm");
        Date end = DateUtil.parse(DateUtil.format(endTime, "yyyy-MM-dd HH:mm:ss"), "yyyy-MM-dd HH:mm");
        if (type.equals("1")){
            start = DateUtil.offset(start, DateField.MINUTE, 1);
        }else if (type.equals("2")){
            start = DateUtil.offset(start, DateField.MINUTE, 1);
            end = DateUtil.offset(end, DateField.MINUTE, -1);
        }else if (type.equals("3")){
            end = DateUtil.offset(end, DateField.MINUTE, -1);
        }
        while(start.compareTo(end)<=0) {
            //新增离线数据
            GantryCraneCaData gantryCraneCaData = new GantryCraneCaData();
            gantryCraneCaData.setRunningState("0");
            gantryCraneCaData.setDeviceNo(deviceNo);
            gantryCraneCaData.setDataTime(start);
            gantryCraneCaData.setCreateTime(start);
            gantryCraneCaData.setLoadCapacity(new BigDecimal("0"));
            offlineGantryCraneCaData.add(gantryCraneCaData);
            start=DateUtil.offset(start, DateField.MINUTE, 1);
        }
        return offlineGantryCraneCaData;
    }
}



